package com.chatplus.application.service.account.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chatplus.application.common.logging.SouthernQuietLogger;
import com.chatplus.application.common.logging.SouthernQuietLoggerFactory;
import com.chatplus.application.dao.account.UserProductLogDao;
import com.chatplus.application.dao.basedata.ProductDao;
import com.chatplus.application.domain.dto.AdminConfigDto;
import com.chatplus.application.domain.entity.account.UserEntity;
import com.chatplus.application.domain.entity.account.UserProductLogEntity;
import com.chatplus.application.domain.entity.basedata.ProductEntity;
import com.chatplus.application.enumeration.ProductTypeEnum;
import com.chatplus.application.service.account.UserProductLogService;
import com.chatplus.application.service.account.UserService;
import com.chatplus.application.service.basedata.ConfigService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户套餐记录业务逻辑实现
 *
 * <p>Table: t_user_product_log - 用户套餐记录</p>
 *
 * @author developer
 * @see UserProductLogEntity
 */
@Service
public class UserProductLogServiceImpl extends ServiceImpl<UserProductLogDao, UserProductLogEntity> implements UserProductLogService {
    private static final SouthernQuietLogger LOGGER = SouthernQuietLoggerFactory.getLogger(UserProductLogServiceImpl.class);

    private final ProductDao productDao;
    private final ConfigService configService;
    private final UserService userService;

    public UserProductLogServiceImpl(ProductDao productDao, ConfigService configService, UserService userService) {
        this.productDao = productDao;
        this.configService = configService;
        this.userService = userService;
    }

    @Override
    public void addProductToUser(Long userId, Long productId, Long orderId) {
        ProductEntity productEntity = productDao.selectById(productId);
        if (productEntity == null) {
            LOGGER.message("套餐不存在")
                    .context("userId", userId)
                    .context("productId", productId)
                    .context("orderId", orderId)
                    .error();
            return;
        }
        UserProductLogEntity userProductLogEntity = new UserProductLogEntity();
        userProductLogEntity.setUserId(userId);
        userProductLogEntity.setProductId(productId);
        userProductLogEntity.setOrderId(orderId);
        userProductLogEntity.setChatCalls(productEntity.getCalls());
        userProductLogEntity.setImgCalls(productEntity.getImgCalls());
        userProductLogEntity.setProductType(ProductTypeEnum.TIME_CARD);
        userProductLogEntity.setSubsStartTime(Instant.now());
        if (productEntity.getDays() > 0) {
            // 有时效的次卡
            userProductLogEntity.setSubsEndTime(Instant.now().plus(productEntity.getDays(), ChronoUnit.DAYS));
        } else {
            // 无时效的次卡 - 默认有效期100年
            userProductLogEntity.setSubsEndTime(Instant.now().plus(100, ChronoUnit.YEARS));
        }
        super.save(userProductLogEntity);
    }

    @Override
    public void adminAddProductToUser(Long userId, Integer addChatCalls, Integer addImgCalls) {
        UserProductLogEntity userProductLogEntity = new UserProductLogEntity();
        userProductLogEntity.setUserId(userId);
        userProductLogEntity.setChatCalls(addChatCalls);
        userProductLogEntity.setImgCalls(addImgCalls);
        userProductLogEntity.setProductId(-1L);
        userProductLogEntity.setOrderId(-1L);
        userProductLogEntity.setProductType(ProductTypeEnum.TIME_CARD);
        userProductLogEntity.setSubsStartTime(Instant.now());
        userProductLogEntity.setSubsEndTime(Instant.now().plus(100, ChronoUnit.YEARS));
        super.save(userProductLogEntity);
    }

    @Override
    public void addSubscribeToUser(Long userId) {
        // 检查用户剩余有效期还有多少天
        UserEntity userEntity = userService.getById(userId);
        if (userEntity == null) {
            LOGGER.message("用户不存在")
                    .context("userId", userId)
                    .error();
            return;
        }
        Instant vipExpiredTime = userEntity.getVipExpiredTime();
        long betweenDay = Duration.between(Instant.now(), vipExpiredTime).toDays();
        if (vipExpiredTime == null || vipExpiredTime.isBefore(Instant.now()) || betweenDay < 15) {
            // 过期用户不做处理
            return;
        }
        UserProductLogEntity userProductLogEntity = new UserProductLogEntity();
        userProductLogEntity.setUserId(userId);
        userProductLogEntity.setProductType(ProductTypeEnum.SUBSCRIPTION_CARD);
        AdminConfigDto adminConfigDto = configService.getSystemConfig();
        // 获取最新的一条有效的月卡记录
        Instant subsStartTime = Instant.now();
        userProductLogEntity.setChatCalls(adminConfigDto.getVipMonthCalls());
        userProductLogEntity.setImgCalls(adminConfigDto.getVipMonthImgCalls());
        List<UserProductLogEntity> subscriptionCardList = getExpirationCardList(userId);
        // 如果有月卡记录，时间顺延即可
        if (CollectionUtils.isNotEmpty(subscriptionCardList)) {
            // 获取subscriptionCardList时间最大的一条记录
            subsStartTime = subscriptionCardList.stream()
                    .filter(subscriptionCard -> subscriptionCard.getProductType() == ProductTypeEnum.SUBSCRIPTION_CARD)
                    .map(UserProductLogEntity::getSubsEndTime)
                    .max(Instant::compareTo)
                    .orElse(Instant.now());
        }
        userProductLogEntity.setSubsStartTime(subsStartTime);
        userProductLogEntity.setSubsEndTime(subsStartTime.plus(1, ChronoUnit.MONTHS));
        super.save(userProductLogEntity);
    }

    // 获取最新的一条月卡记录
    @Override
    public List<UserProductLogEntity> getExpirationCardList(Long userId) {
        return list(Wrappers.<UserProductLogEntity>lambdaQuery()
                .eq(UserProductLogEntity::getUserId, userId)
                .ge(UserProductLogEntity::getSubsEndTime, Instant.now())
                .and(wrapper -> wrapper.gt(UserProductLogEntity::getImgCalls, 0)
                        .or().gt(UserProductLogEntity::getChatCalls, 0))
                .orderByDesc(UserProductLogEntity::getCreatedAt));
    }

    @Override
    public int getUserChatCalls(Long userId) {
        // 获取套餐
        List<UserProductLogEntity> expirationCardList = getExpirationCardList(userId);
        expirationCardList = expirationCardList.stream()
                .filter(entity -> entity.getSubsEndTime() != null) // 过滤掉空值
                .filter(entity -> entity.getChatCalls() > 0)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(expirationCardList)) {
            return 0;
        }
        return expirationCardList.stream().map(UserProductLogEntity::getChatCalls).reduce(0, Integer::sum);
    }

    @Override
    public int getUserImgCalls(Long userId) {
        // 获取套餐
        List<UserProductLogEntity> expirationCardList = getExpirationCardList(userId);
        expirationCardList = expirationCardList.stream()
                .filter(entity -> entity.getSubsEndTime() != null) // 过滤掉空值
                .filter(entity -> entity.getImgCalls() > 0)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(expirationCardList)) {
            return 0;
        }
        return expirationCardList.stream().map(UserProductLogEntity::getImgCalls).reduce(0, Integer::sum);
    }

    @Override
    public void reduceChatCalls(Long userId, Integer modelWeight) {
        if (userId == null || modelWeight <= 0) {
            return;
        }
        // 获取套餐
        List<UserProductLogEntity> expirationCardList = getExpirationCardList(userId);
        expirationCardList = expirationCardList.stream()
                .filter(entity -> entity.getSubsEndTime() != null) // 过滤掉空值
                .filter(entity -> entity.getChatCalls() > 0)
                .sorted(Comparator.comparing(UserProductLogEntity::getSubsEndTime))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(expirationCardList)) {
            return;
        }
        int chatCalls = modelWeight;
        for (UserProductLogEntity userProductLogEntity : expirationCardList) {
            if (userProductLogEntity.getChatCalls() >= chatCalls) {
                userProductLogEntity.setChatCalls(userProductLogEntity.getChatCalls() - chatCalls);
                super.updateById(userProductLogEntity);
                break;
            } else {
                chatCalls -= userProductLogEntity.getChatCalls();
                userProductLogEntity.setChatCalls(0);
                super.updateById(userProductLogEntity);
            }
        }
    }
}
